using System;
using System.Windows.Forms;
using System.Xml;
using System.Xml.XPath ;
using EnvDTE;
using AopDotNet.CodeModelXMLTreeBuilder;
using AopDotNet.Editor ;
using System.Collections ;
using System.Text.RegularExpressions  ;
using System.Text;
using System.IO ;

using System.CodeDom.Compiler  ;
using System.CodeDom ;


namespace AopDotNet
{
	public enum Language {CSharp,VB,JSharp};
	namespace AspectWeaver
	{
		/// <summary>
		/// Summary description for Class1.
		/// </summary>

		public enum WeavingLevel {Statement,Method};

		
		public class Weaver
		{
			public CodeModelBuilder AdvisedCodeModelTree;
			//private Hashtable cachedCodeElements;
			private static string USPattern;
			private static string nameSpacePattern;
			private ICodeGenerator codeGenerator;
			private Introducer introducer;
			private Hashtable fileUsingStatments;
			private Hashtable fileToFilesUsingStatments;
			private Hashtable markedEditPoints;
			private Language curLang;//1 csharp 2 vb 3 jsharp
			public EditingMonitor editingMonitor;

		

			public Weaver(ICodeGenerator codgen,Language lang,Project proj,EditingMonitor editMon)
			{
				Helper.curProj=proj;
				//cachedCodeElements=new Hashtable (20,(float)0.3);
				codeGenerator =codgen;
				fileUsingStatments=new Hashtable (30);
				fileToFilesUsingStatments=new Hashtable (30);
				curLang=lang;
				if (lang==Language.VB )
					nameSpacePattern=@"(?<namespace>\w[^\n]*)";
				else
					nameSpacePattern=@"(?<namespace>\w[^;]*)";
				editingMonitor=editMon;
				
			}
			public void Weave(CodeModelBuilder AdvisedCodeModel,Hashtable editPoints)
			{
				this.AdvisedCodeModelTree=AdvisedCodeModel;
				CodeEditor.AdvisedCodeModelTree= AdvisedCodeModel;
				this.markedEditPoints=editPoints;
				introducer=new Introducer (codeGenerator, AdvisedCodeModel);
				fileUsingStatments=new Hashtable (30);
				WeaveTheIntroductions();
				WeaveTheAdvices();
				
			}
			private void WeaveTheAdvices()
			{
				XPathNavigator navigator =AdvisedCodeModelTree.GetXmlDocument () .CreateNavigator();
				XPathNodeIterator advicesNodes=navigator .Select ("//advices");
				
				string adviceType,aspectName,adviceFunctionName;
			
				while(advicesNodes.MoveNext())
				{
					XmlNode currentAdvicesNode=((IHasXmlNode )advicesNodes.Current).GetNode ();
					XmlNode advisedElement = currentAdvicesNode.ParentNode ;
					CodeElement advisedCodeElement=Helper.GetCodeElementFromCodeModel (advisedElement,AdvisedCodeModelTree);

					Helper.OpenItemFile(advisedCodeElement);
				
					foreach(XmlNode adviceNode in currentAdvicesNode.ChildNodes )/*aspect precedence and advise precedence goes here*/
					{
					
						/*before then around then after may use xslt*/
						XmlNode advisedMethod=adviceNode.SelectSingleNode ("ancestor::method");
					
						adviceType=adviceNode.Attributes ["type"].Value ;
						aspectName=adviceNode.Attributes["aspect"].Value;
						adviceFunctionName=adviceNode.Attributes["method"].Value;

						CodeElement aspectMethod=Helper.GetAspectElement (adviceFunctionName,"method",aspectName,AdvisedCodeModelTree );
						WeaveUsingStatements(advisedMethod,aspectMethod);

					
						if (adviceNode.Attributes ["startpoint"]==null && adviceNode.Attributes ["endpointid"]==null)
							WeaveAdviceMethodLevel(advisedMethod ,adviceType ,adviceFunctionName ,aspectName );
						else
							WeaveAdviceStatementLevel (advisedMethod,adviceType,adviceFunctionName ,aspectName ,adviceNode.Attributes ["startpointid"].Value ,adviceNode.Attributes ["endpointid"].Value  );
					
					}
				}
			}
			private void WeaveTheIntroductions()
			{
				XPathNavigator navigator =AdvisedCodeModelTree.GetXmlDocument () .CreateNavigator();
				XPathNodeIterator introductionsNodes=navigator .Select ("//introductions");
				while(introductionsNodes.MoveNext())
				{
					XmlNode currentIntroNode=((IHasXmlNode )introductionsNodes.Current).GetNode ();
					XmlNode introdcedToElement = currentIntroNode.ParentNode ;
					foreach(XmlNode introducedNode in currentIntroNode.ChildNodes )/*aspect precedence and advise precedence goes here*/
					{
						//check to see if this element already exists
						//	CodeElement introducedCodelement=GetAspectElement (introducedNode.Attributes ["name"].Value ,introducedNode.Name ,introducedNode.Attributes ["aspect"].Value );
						CodeElement introducedToCodeElement=(CodeElement)AdvisedCodeModelTree.codeElements[Int32.Parse(introdcedToElement.Attributes ["id"].Value )];
						Helper.OpenItemFile(introducedToCodeElement);
					
						switch(introdcedToElement.Name )
						{
							case "class":
								introducer.AddToClass((CodeClass)introducedToCodeElement,introducedNode,editingMonitor);
								break;
							case "method":
								introducer.AddToMethod((CodeFunction )introducedToCodeElement,introducedNode );
								break;
							case "member":
								introducer.AddToVariable((CodeVariable )introducedToCodeElement,introducedNode );
								break;
							case "namespace":
								introducer.AddToNameSpace((EnvDTE.CodeNamespace) introducedToCodeElement,introducedNode,editingMonitor );
								break;
						}
					
						//					Helper.SaveTheElementFile (introducedToCodeElement);
					}
				}
			}

			void WeaveUsingStatements(XmlNode objectNode,CodeElement aspectElement)
			{
				string objectFilePath=GetFileName(objectNode);
				string aspectFilePath=aspectElement.ProjectItem.get_FileNames (0);
	
				string objectFileName=Helper.GetFileNameFromFullPath (objectFilePath);
				string aspectFileName=Helper.GetFileNameFromFullPath (aspectFilePath);
		
				//f2fUSParsingState res=CheckFileUSState(objectFileName,aspectFileName );

				ArrayList  DiffUsedNamespaces;
				ParseUsingStatementsInFile(objectFilePath );
				ParseUsingStatementsInFile(aspectFilePath );
				DiffUsedNamespaces=CompareUsingStatementsInFiles(objectFileName ,aspectFileName );
				AddUsingStatementToFile(DiffUsedNamespaces ,Helper.GetCodeElementFromCodeModel (objectNode,this.AdvisedCodeModelTree  ),objectFileName);

				/*
				switch (res)
				{
					case f2fUSParsingState.NotParsed :
							ParseUsingStatementsInFile(objectFilePath );
							ParseUsingStatementsInFile(aspectFilePath );
							DiffUsedNamespaces=CompareUsingStatementsInFiles(objectFileName ,aspectFileName );
							AddUsingStatementToFile(DiffUsedNamespaces ,Helper.GetCodeElementFromCodeModel (objectNode,this.AdvisedCodeModelTree  ));
							break;
					case f2fUSParsingState.FirstParsed :
						ParseUsingStatementsInFile(aspectFilePath );
						DiffUsedNamespaces=CompareUsingStatementsInFiles(objectFileName ,aspectFileName );
						AddUsingStatementToFile(DiffUsedNamespaces ,Helper.GetCodeElementFromCodeModel (objectNode,this.AdvisedCodeModelTree  ));
						break;
					case f2fUSParsingState.SecondParsed :
						DiffUsedNamespaces=CompareUsingStatementsInFiles(objectFileName ,aspectFileName );
						AddUsingStatementToFile(DiffUsedNamespaces ,Helper.GetCodeElementFromCodeModel (objectNode,this.AdvisedCodeModelTree  ));
						break;
					case f2fUSParsingState.ParsedAndCompared :
						return;
					
				}
				*/

			}
			void ParseUsingStatementsInFile(string filePath )
			{
				string fileName=Helper.GetFileNameFromFullPath (filePath);
				if (fileUsingStatments.Contains (fileName))
					return;
		
				if (USPattern==null)
				{
					USPattern=LanguageEngine.GenerateUsingStatementPattern ("MMMM",codeGenerator );
					USPattern=USPattern.Replace ("MMMM",nameSpacePattern );
				}
		
				//StreamReader fileReader=new StreamReader (filePath);
				//string fileContent=fileReader.ReadToEnd ();

				TextDocument doc=(TextDocument)Helper.curProj.ProjectItems.Item (fileName).Document .Object ("");
				string fileContent=doc.StartPoint .CreateEditPoint ().GetText (doc.EndPoint ); 
				MatchCollection matchedUSs=Regex.Matches(fileContent ,USPattern);
				string usedNameSpaces="";
				foreach (Match matchedUS in matchedUSs )
				{
					string usedNameSpace=matchedUS.Groups ["namespace"].Value ;
					Match m =Regex.Match (usedNameSpace,@".\s*[*]");
					if (m.Success )
						usedNameSpace=usedNameSpace.Remove (m.Index ,m.Length );
					usedNameSpaces=usedNameSpaces+usedNameSpace+";";
				
				}
				fileUsingStatments.Add (fileName,usedNameSpaces );
				//	fileReader.Close ();
			
			}
			ArrayList CompareUsingStatementsInFiles(string objectFileName,string aspectFileName )
			{
				string objectFileUSs=this.fileUsingStatments [objectFileName ].ToString ();
				string aspectFileUSs=this.fileUsingStatments [aspectFileName ].ToString ();

			
				ArrayList objectFileUsedNamespaces=new ArrayList (Regex.Split (objectFileUSs,";"));
				ArrayList aspectFileUsedNamespaces=new ArrayList (Regex.Split (aspectFileUSs,";"));
				ArrayList newNameSpaces=new ArrayList(20);
				int startIndex=0,index=0;
				index=aspectFileUSs.IndexOf (";",startIndex);
				while (index!=-1)
				{
					string usedName=aspectFileUSs.Substring (startIndex,index-startIndex);
					usedName=usedName.Trim ();
					usedName=usedName.Replace (" ",@"\s*");
					startIndex=index+1;
					index=aspectFileUSs.IndexOf (";",startIndex);

					Match matched=Regex.Match (objectFileUSs,usedName);
					if (matched.Success )
						continue;
					else
					{
						newNameSpaces.Add (usedName.Replace (@"\s*"," "));
					}

				}
				/*
				for(int i=0;i<aspectFileUsedNamespaces.Count ;i++ )
				{
					if (aspectFileUsedNamespaces[i].ToString()=="")
						aspectFileUsedNamespaces.RemoveAt (i);
					else
						aspectFileUsedNamespaces[i]=aspectFileUsedNamespaces[i].ToString ().Replace (" ","");
				}
				for(int i=0;i<objectFileUsedNamespaces.Count ;i++ )
				{
					if (objectFileUsedNamespaces[i].ToString()=="")
						objectFileUsedNamespaces.RemoveAt (i);
					else
						objectFileUsedNamespaces[i]=objectFileUsedNamespaces[i].ToString ().Replace (" ","");
				}
			
				ArrayList newNameSpaces=new ArrayList(20);
			
				for(int i=0;i<aspectFileUsedNamespaces.Count ;i++ )
				{
					if (aspectFileUsedNamespaces [i].ToString ()!="")
					{
						if (objectFileUsedNamespaces.Contains (aspectFileUsedNamespaces [i]))
							continue;
						else
							newNameSpaces.Add (aspectFileUsedNamespaces [i].ToString ());
					}
				}*/
				return newNameSpaces;
			}
			void AddUsingStatementToFile(ArrayList  Namespaces ,CodeElement codeElement ,string fileName)
			{
				if (Namespaces.Count ==0)
					return;
				EditPoint startOfDoc;

				if (curLang==Language.JSharp )
				{
					/*REM*/
					EditPoint st=codeElement.StartPoint.CreateEditPoint();
					this.editingMonitor .UpdateEditPoint (ref st);
					startOfDoc=st;
					TextRanges ran=null;
					string USs=(string)this.fileUsingStatments [fileName];
				
					string us=":Wh*"+USPattern.Replace (nameSpacePattern ,USs.Substring (0,USs.IndexOf (";")))+":Wh*";
					if (st.FindPattern (us,(int)(vsFindOptions.vsFindOptionsRegularExpression|vsFindOptions.vsFindOptionsFromStart),ref startOfDoc,ref ran)==true)
					{
						string s="ddd";
					}
					else
					{
					}
				}
				else
				{
					/*REMF*/
					startOfDoc=codeElement.StartPoint.CreateEditPoint();
					this.editingMonitor .UpdateEditPoint (ref startOfDoc);
					startOfDoc.MoveToAbsoluteOffset (0);
				}
				if (curLang!=Language.JSharp )
				this.editingMonitor.StartLog(ref startOfDoc,true);/*REMN*/ 
				StringBuilder newNameSpaces=new StringBuilder ();
				foreach(string nameSpace in Namespaces )
				{
					string strUsing=USPattern.Replace (nameSpacePattern ,nameSpace);
					
					startOfDoc.Insert (strUsing);
					startOfDoc.Insert ("\n");
				//	startOfDoc.Insert ("\n");/*Inser*/
					newNameSpaces.Append (nameSpace+";");
				}
				if (curLang!=Language.JSharp )
				this.editingMonitor.EndLog(ref startOfDoc);

				if (this.fileUsingStatments .Contains (fileName))
				{
					string FileUSs=this.fileUsingStatments [fileName ].ToString ();
					FileUSs+=newNameSpaces.ToString ();
					this.fileUsingStatments [fileName ]=FileUSs;
				}
				else
				{
					this.fileUsingStatments .Add (fileName,newNameSpaces);
				}
				//			Helper.SaveTheElementFile (codeElement);
			}
			/*
			f2fUSParsingState CheckFileToFileParsingUSRelation(string objectFileName,string aspectFileName )
			{
				bool objectFileParsed=fileUsingStatments.Contains (objectFileName);
				bool aspectFileParsed=fileUsingStatments.Contains (aspectFileName);

				if (objectFileParsed&aspectFileParsed)
				{
					string filesRelated=fileToFilesUsingStatments [objectFileName].ToString ();
					if (filesRelated.IndexOf (aspectFileName )!=-1)
						return f2fUSParsingState.ParsedAndCompared ; //return true
					else
						return f2fUSParsingState.AllParsed ;//return false
				
				}
				else
				{
					if (objectFileParsed==false&aspectFileParsed==false)
						return f2fUSParsingState.NotParsed ;
					else
					{
						if (objectFileParsed)
							return f2fUSParsingState.FirstParsed;
						else
							return f2fUSParsingState.SecondParsed;
					
					}
				}

			}
			*/
			string GetFileName(XmlNode Node)
			{
				CodeElement element1=Helper.GetCodeElementFromCodeModel (Node,AdvisedCodeModelTree);
				//return Helper.GetFileNameFromFullPath (element1.ProjectItem.get_FileNames (0));
				return element1.ProjectItem.get_FileNames (0);
			}

			
		
			/// <summary>
			/// weave the advices that affect a code statement like call
			/// </summary>
			/// <param name="methodNode">the base method</param>
			/// <param name="adviceType"></param>
			/// <param name="adviceFunctionName"></param>
			/// <param name="aspectName"></param>
			/// <param name="strStartIndex">the index of the start of the code statement</param>
			/// <param name="strEndIndex">the index of the end of the code statement</param>
			private void WeaveAdviceStatementLevel(XmlNode methodNode,string  adviceType ,string adviceFunctionName ,string aspectName ,string strStartPointId,string strEndPointId)
			{
				/*REMF*/
				EditPoint startStatementPoint=(EditPoint) markedEditPoints [Int32.Parse (strStartPointId)];
				editingMonitor.UpdateEditPoint(ref startStatementPoint);
				EditPoint endStatementPoint=(EditPoint) markedEditPoints [Int32.Parse (strEndPointId)];
				editingMonitor.UpdateEditPoint(ref endStatementPoint);
			
				EditPoint statementstart=(EditPoint)this.markedEditPoints [Int32.Parse (strStartPointId)];
				EditPoint statementend=(EditPoint)this.markedEditPoints [Int32.Parse (strEndPointId)];
				//BIND PARAMETER what it should do?
				/*Missing*/
			
				CodeFunction aspectFunction=(CodeFunction)Helper.GetAspectElement(adviceFunctionName,"method",aspectName,AdvisedCodeModelTree );

				if (aspectFunction==null)
				{
					throw new ArgumentException ("Class: "+aspectName+"\n"+
						"can't find the following function: "+adviceFunctionName);
				}
				AspectCodeTranslator translator=new AspectCodeTranslator (aspectFunction,methodNode,adviceType,this ,codeGenerator  );
				translator.SetAdvisedCodeBoundaries (statementstart,statementend);
				StringBuilder strAspectFunction= translator.TranslateAspectSpecificCode();
			
				string methodID =methodNode.Attributes ["id"].Value ;
				CodeFunction advisedMethod=(CodeFunction)AdvisedCodeModelTree.codeElements[Int32.Parse(methodID)];

				//BindParameters(advisedMethod,aspectFunction,ref strAspectFunction);

				EditPoint editPoint=null ;
				switch(adviceType)
				{
					case "before":
						/*REMF*/
						//editPoint=Helper.GetEditPointBeforeStatementInFunction (ref advisedMethod,startIndex  );
						editPoint=startStatementPoint;
						editingMonitor.StartLog (ref editPoint,true);
					
						editPoint.Insert ("\n");
					
						break;
					case "after":
					
						//editPoint=Helper.GetEditPointAfterStatementInFunction (ref advisedMethod,startIndex ,length );
						editPoint=endStatementPoint;
						editingMonitor.StartLog (ref editPoint,true);
						editPoint.Insert ("\n");
					
						break;
					case "around":
						editPoint=endStatementPoint;
						editingMonitor.StartLog (ref editPoint,true);
						//MessageBox.Show (strtPoint.GetText (endPoint));
						startStatementPoint.Cut (endStatementPoint,false);
						editPoint=startStatementPoint;
						break;
				}
				editPoint.Insert("\n"+strAspectFunction.ToString ());/*Insert*/
				editingMonitor.EndLog (ref editPoint);
				//			Helper.SaveTheElementFile ((CodeElement)advisedMethod);

			}


			/// <summary>
			/// weave advices that affect all the method body like execution
			/// </summary>
			/// <param name="methodNode">the base function</param>
			/// <param name="adviceType"></param>
			/// <param name="adviceFunctionName"></param>
			/// <param name="aspectName"></param>
			private void WeaveAdviceMethodLevel(XmlNode methodNode,string adviceType,string adviceFunctionName ,
				string aspectName  )
			{
				CodeFunction aspectFunction=(CodeFunction)Helper.GetAspectElement(adviceFunctionName,"method",aspectName,AdvisedCodeModelTree );

				if (aspectFunction==null)
				{
					throw new ArgumentException ("Class: "+aspectName+"\n"+
						"can't find the following function: "+adviceFunctionName);
				}
			
				AspectCodeTranslator translator=new AspectCodeTranslator (aspectFunction,methodNode,adviceType,this, codeGenerator );
				StringBuilder strAspectFunction= translator.TranslateAspectSpecificCode();
			
				string methodID =methodNode.Attributes ["id"].Value ;
				CodeFunction advisedMethod=(CodeFunction)Helper.GetCodeElementFromCodeModel (methodNode,AdvisedCodeModelTree) ; //AdvisedCodeModelTree.codeElements[Int32.Parse(methodID)];

				BindParameters(advisedMethod,methodNode,aspectFunction,ref strAspectFunction);

				TextPoint editPoint=null ;
				EditPoint edit=null;
				switch(adviceType)
				{
					case "before":
						/*REMF*/
						editPoint=advisedMethod.GetStartPoint(vsCMPart.vsCMPartBody);
						edit =editPoint.CreateEditPoint();
						editingMonitor.StartLog (ref edit,false);
						break;
					case "after":
						editPoint=advisedMethod.GetEndPoint(vsCMPart.vsCMPartBody);
						edit =editPoint.CreateEditPoint();
						editingMonitor.StartLog (ref edit,false);
						break;
					case "around":
						TextPoint strtPoint=advisedMethod.GetStartPoint(vsCMPart.vsCMPartBody);
						TextPoint endPoint=advisedMethod.GetEndPoint(vsCMPart.vsCMPartBody);
						edit =endPoint.CreateEditPoint();
						editingMonitor.StartLog (ref edit,false);
						strtPoint.CreateEditPoint().Cut(endPoint,false);
						editPoint=strtPoint;
						break;
				}
			
			
				edit.Insert(strAspectFunction.ToString ());/*Insert*/
				editingMonitor.EndLog (ref edit);

			}
	
			/// <summary>
			/// the parameters passed to the aspect function are converted to the parametes passed to the base function
			/// </summary>
			/// <param name="advisedMethod">the base function</param>
			/// <param name="aspectMethod">the aspect function</param>
			/// <param name="strAspectFunction">the code of the aspect function</param>
			void BindParameters(CodeFunction advisedMethod, XmlNode advisedMethodNode,CodeFunction aspectMethod,ref StringBuilder strAspectFunction )
			{
				/*Missing*///First parameter is an object of the same type as this so that u can access this instead of GetCurrentObject*/
				CodeElements advisedParams = advisedMethod.Parameters;
				CodeElements aspectParams = aspectMethod.Parameters;
				if (aspectParams.Count ==0)
					return;
				int i=1,j=1,offset=0;
				
				//get the class of the method
				XmlNode classNode=advisedMethodNode.SelectSingleNode ("ancestor::class");
								
				//get the First param
				CodeParameter aspectCP =(CodeParameter)aspectParams.Item(i);

				bool res=CheckFirstParam(classNode,aspectCP.Type.AsString );

				if (res)
				{
					//if so then this parameter is converted to this
					CodeThisReferenceExpression thisExp=new CodeThisReferenceExpression ();
					StringWriter swThisExp=new StringWriter ();
					codeGenerator .GenerateCodeFromExpression (thisExp,swThisExp,null);
					ReplaceArgumentName(aspectCP.Name,ref strAspectFunction,swThisExp.ToString ());
					i++;
					offset=1;
				}

				for(;i<=aspectParams.Count;i++)
				{
					aspectCP =(CodeParameter)aspectParams.Item(i);

					for(j=i-offset;j<=advisedParams.Count;j++)
					{
						CodeParameter advisedCP =(CodeParameter)advisedParams.Item(j);
						if(aspectCP.Type.AsString==advisedCP.Type.AsString)
						{
							ReplaceArgumentName(aspectCP.Name,ref strAspectFunction,advisedCP.Name);

							/*						for (int l=0;l<matchedArgRef.Count ;l++)
													{
														inputString =inputString.Replace (matchedArgRef[l].Value ,adviesdCP.Name,matchedArgRef[l].Index ,matchedArgRef[l].Length );
													}

													CodeVariableReferenceExpression argRef2=new CodeVariableReferenceExpression (aspectCP.Name );
													codeGenerator .GenerateCodeFromExpression (argRef2,swArgRefExpr,null);
													matchedArgRef=Regex.Matches  (inputString ,swArgRefExpr.ToString ());
													for (int l=0;l<matchedArgRef.Count ;l++)
													{
														inputString=inputString .Replace (matchedArgRef[l].Value ,adviesdCP.Name,matchedArgRef[l].Index ,matchedArgRef[l].Length );
													}
							*/
							continue;
						}
					}
				}
				
			}

			
			/// <summary>
			/// check to see if the aspect function has the first parameter of the type of the advised class
			/// or a type that is parent of the type of the advised class
			/// </summary>
			/// <param name="classID">id of the advised class</param>
			/// <param name="paramType">the type of the parameter of the aspecct function</param>
			/// <returns></returns>
			private bool CheckFirstParam(XmlNode classNode,string paramType)
			{
				string classID=classNode.Attributes ["id"].Value ;
				string className=classNode.Attributes ["name"].Value.Trim () ;
				
				//check if they are the same type
				if (paramType.Length >className.Length )
				{
					Match m=Regex.Match (paramType,@"(\W|^)"+className+@"$") ;
					if (m.Success )
						return true;
				}
				else
				{
					Match m=Regex.Match (className,@"(\W|^)"+paramType+@"$") ;
					if (m.Success )
						return true;
				
				}

				//check if the type of the param is like the type of one of the bases
				CodeClass theClass=(CodeClass)Helper.GetCodeElementFromCodeModel (classNode,this.AdvisedCodeModelTree );
				
				EditPoint st=theClass.StartPoint .CreateEditPoint ();
				this.editingMonitor .UpdateEditPoint (ref st);
				EditPoint end=theClass.EndPoint.CreateEditPoint ();
				this.editingMonitor .UpdateEditPoint (ref end);
				string strClass=st.GetText (end );	
					
				string strBases=CodeInspector.GetBases (className,strClass,codeGenerator);
				ArrayList basesNames=CodeInspector .ExtractBasesNames (strBases,codeGenerator );
				for (int i=0;i<basesNames.Count ;i++)
				{
					string baseClass=(string)basesNames[i];
					if (Regex.Match (paramType,@"\W"+baseClass.Trim ()+"$").Success )
						return true;
				}
				return false;
				
			}
			/// <summary>
			/// Used in Bind Parameter to change the names of the advice function parametera
			/// to match the names of the original function
			/// </summary>
			/// <param name="oldArg"></param>
			/// <param name="function"></param>
			/// <param name="newArg"></param>
			/// <editdate>10/3/2003 5:07:14 PM</editdate>
			void ReplaceArgumentName(string oldArg,ref StringBuilder function,string newArg)
			{
				//	CodeArgumentReferenceExpression argRefExpr=new CodeArgumentReferenceExpression (@"\W+"+oldArg+@"\W+" );
				CodeArgumentReferenceExpression argRefExpr=new CodeArgumentReferenceExpression (@"(?<bef>\W)"+oldArg+@"(?<aft>\W)" );
						
				StringWriter swArgRefExpr=new StringWriter ();
				codeGenerator .GenerateCodeFromExpression (argRefExpr,swArgRefExpr,null);
				Match matchedArgRef=Regex.Match  (function.ToString (),swArgRefExpr.ToString ());
				int replacement=0;
				while (matchedArgRef.Success )
				{
					function.Replace (oldArg,newArg,matchedArgRef.Index +replacement ,matchedArgRef.Length );
					replacement +=newArg.Length -oldArg.Length ;
					matchedArgRef=matchedArgRef.NextMatch ();
				}
				/*
				foreach (Match m in matchedArgRef)
				{
					function.Replace (oldArg,newArg,m.Index +dif,m.Value .Length );
					dif=oldArg.Length-m.Value .Length ;
				}*/

			}
		}
	}

}
#region caching
/*	public CodeElement GetCodeElement(string fileName,string className,string elementName)
		{
			CodeElement result=null;
			if (IsCached(fileName,className,elementName,ref result))
				return result;

			CodeElements els=curProj.ProjectItems.Item(fileName).FileCodeModel.CodeElements;
			foreach (CodeElement ce in els)
			{
				if(ce.Kind==vsCMElement.vsCMElementNamespace)
				{
					EnvDTE.CodeNamespace nameSpace=(EnvDTE.CodeNamespace)ce;
					foreach(CodeElement ce2 in nameSpace.Members)
					{
						if (ce2.Name == className)
						{
							CodeClass codeClass=(CodeClass)ce2;
							foreach(CodeElement ce3 in codeClass.Members)
							{
								if (ce3.Name ==elementName)
								{
									string key=fileName+className+elementName;
									cachedCodeElements.Add (key,ce3);
									return ce3;
								}
							}
						}
					}
				}
				else
					if(ce.Kind==vsCMElement.vsCMElementClass )
                    {
					CodeClass codeClass=(CodeClass)ce;
					foreach(CodeElement ce3 in codeClass.Members)
					{
						if (ce3.Name ==elementName)
						{
							string key=fileName+className+elementName;
							cachedCodeElements.Add (key,ce3);
							return ce3;
						}
					}
                    }
			}	

			return null;
		}
		
		private bool IsCached(string fileName,string className,string elementName,ref CodeElement res)
		{
			string key=fileName+className+elementName;
			if (cachedCodeElements.Contains (key))
			{
				res=(CodeElement)cachedCodeElements[key];
				return true;
			}
			else
				return false;
			
		}
	*/	
///////////////////////////////////////////////////////////////////////
#endregion